package com.jinzhi.jzweb.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.jinzhi.common.base.CoreServiceImpl;
import com.jinzhi.common.service.DictService;
import com.jinzhi.common.utils.Result;
import com.jinzhi.common.utils.StringUtil;
import com.jinzhi.jzweb.dao.TrackDrawDao;
import com.jinzhi.jzweb.domain.TrackDrawDO;
import com.jinzhi.jzweb.domain.TrackDrawDownLoadDO;
import com.jinzhi.jzweb.pojo.TrackDrawName4;
import com.jinzhi.jzweb.pojo.TrackDrawName4Export;
import com.jinzhi.jzweb.pojo.TrackDrawNameVO;
import com.jinzhi.jzweb.pojo.XinJiangTrackVO;
import com.jinzhi.jzweb.service.TrackDrawService;
import com.jinzhi.jzweb.utils.*;
import io.swagger.models.auth.In;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.security.SecureRandom;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 *
 * <pre>
 * 赛道抽签表（存储抽签信息）
 * </pre>
 * <small> 2024-02-28 09:32:18 | lance</small>
 */
@Service
public class TrackDrawServiceImpl extends CoreServiceImpl<TrackDrawDao, TrackDrawDO> implements TrackDrawService {
    @Autowired
    private DictService dictService;

    //查询抽签规则
    public String getRule(){
        Map<String, String> map = new HashMap<>();
        map.put("name", "draw_rule");
        map.put("type", "draw_rule");
        return dictService.selDicBy(map);
    }

    /**
     * 抽签接口
     * @param trackDrawDTO
     * @return
     */
    @Override
    public Result<List<TrackDrawDO>> trackDrawList(TrackDrawDO trackDrawDTO) {
        if (trackDrawDTO.getCbatchId()==null){
            return Result.fail("请先选择抽签批次！");
        }
        //获取检录号规则
        //String rule = getRule();
        Random random = new Random();
        //获取抽签列表
        LinkedList<String> numList = new LinkedList<>();
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.eq("cbatch_id",trackDrawDTO.getCbatchId());
        wrapper.orderBy(true,"sort");
        List<TrackDrawDO> trackDrawDOS = this.selectList(wrapper);

        // 使用 Stream API 过滤出 placeNum 不为空的元素
        List<TrackDrawDO> filteredList = trackDrawDOS.stream()
                .filter(trackDrawDO -> trackDrawDO.getPlaceNum() != null && !trackDrawDO.getPlaceNum().isEmpty())
                .collect(Collectors.toList());

        // 判断是否进行导入学校
        if (trackDrawDOS.size()<=0) {
            return Result.fail("请先导入学校！");
        }
        // 将查询到的学校放入抽签列表中
        for (int i = 1; i <= trackDrawDOS.size(); i++) {
            numList.add(String.valueOf(i));
        }
        // 将指定的检录号从数组中移除
        filteredList.forEach(trackDrawDO ->{
            if(StringUtil.notEmpty(trackDrawDO.getPlaceNum())){
                numList.remove(trackDrawDO.getPlaceNum());
            }
        });

        //打乱一下存放检录号的列表
        Collections.shuffle(numList,random);
        // 遍历设置检录号
        for (TrackDrawDO record : trackDrawDOS) {
            String recordNumber = "";
            Integer recordNumberSort=null;
            //判断检录序号是否需要固定
            if(StringUtil.notEmpty(record.getPlaceNum())){
                recordNumberSort= Integer.valueOf(record.getPlaceNum());
                //recordNumber=rule+record.getPlaceNum();
                recordNumber=record.getPlaceNum();
                record.setRecordNumberSort(Integer.parseInt(record.getPlaceNum()));
                numList.remove(record.getPlaceNum());
            }else{
                recordNumberSort= Integer.valueOf(numList.getFirst());
                //recordNumber=rule+numList.getFirst();
                recordNumber=numList.getFirst();
                record.setRecordNumberSort(Integer.parseInt(numList.getFirst()));
                numList.removeFirst();
            }
            //设置检录号
            record.setRecordNumber(recordNumber);
            record.setRecordNumberSort(recordNumberSort);

        }
        if(null!=trackDrawDOS && !trackDrawDOS.isEmpty()){
            this.updateBatchById(trackDrawDOS);
        }

        return Result.ok(setTemplate(trackDrawDOS));

    }








    /**
     * 抽签接口
     * @param trackDrawDTO
     * @return
     */
    @Override
    public Result<List<TrackDrawDO>> trackDrawList1(TrackDrawDO trackDrawDTO) {
        if (trackDrawDTO.getCbatchId() == null) {
            return Result.fail("请先选择抽签批次！");
        }

        Random random = new Random();
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.eq("cbatch_id", trackDrawDTO.getCbatchId());
        wrapper.orderBy(true, "sort");
        List<TrackDrawDO> trackDrawDOS = this.selectList(wrapper);

        // 判断是否进行导入学校
        if (trackDrawDOS.size() <= 0) {
            return Result.fail("请先导入学校！");
        }

        // 遍历处理选手抽签逻辑
        for (TrackDrawDO record : trackDrawDOS) {
            handlePlayerSelection(record, random);
        }

        if (null != trackDrawDOS && !trackDrawDOS.isEmpty()) {
            this.updateBatchById(trackDrawDOS);
        }

        return Result.ok(setTemplate(trackDrawDOS));
    }

    /**
     * 处理选手抽签逻辑
     */
    private void handlePlayerSelection(TrackDrawDO record, Random random) {
        // 获取所有不为空的选手名称
        List<String> availablePlayers = new ArrayList<>();
        if (StringUtil.notEmpty(record.getName1())) availablePlayers.add(record.getName1());
        if (StringUtil.notEmpty(record.getName2())) availablePlayers.add(record.getName2());
        if (StringUtil.notEmpty(record.getName3())) availablePlayers.add(record.getName3());
        if (StringUtil.notEmpty(record.getName4())) availablePlayers.add(record.getName4());

        // 清空之前的抽签结果
        record.setCheckName1(null);
        record.setCheckName2(null);

        // 如果有固定选手，优先使用固定选手
        if (StringUtil.notEmpty(record.getFixedName1()) || StringUtil.notEmpty(record.getFixedName2())) {
            // 设置固定选手到check_name
            if (StringUtil.notEmpty(record.getFixedName1())) {
                record.setCheckName1(record.getFixedName1());
                availablePlayers.remove(record.getFixedName1());
            }
            if (StringUtil.notEmpty(record.getFixedName2())) {
                record.setCheckName2(record.getFixedName2());
                availablePlayers.remove(record.getFixedName2());
            }

            // 如果固定选手数量不足，从可用选手中随机抽取补充
            if (StringUtils.isEmpty(record.getCheckName1()) && availablePlayers.size() >= 1) {
                int randomIndex = random.nextInt(availablePlayers.size());
                record.setCheckName1(availablePlayers.get(randomIndex));
                availablePlayers.remove(randomIndex);
            }

            if (StringUtils.isEmpty(record.getCheckName2()) && availablePlayers.size() >= 1) {
                int randomIndex = random.nextInt(availablePlayers.size());
                record.setCheckName2(availablePlayers.get(randomIndex));
            }
        } else {
            // 没有固定选手，随机抽取两名选手
            if (availablePlayers.size() >= 2) {
                // 打乱选手顺序
                Collections.shuffle(availablePlayers, random);
                record.setCheckName1(availablePlayers.get(0));
                record.setCheckName2(availablePlayers.get(1));
            } else if (availablePlayers.size() == 1) {
                // 只有一个选手的情况
                record.setCheckName1(availablePlayers.get(0));
                record.setCheckName2(null);
            }
            // 如果没有选手，check_name1和check_name2保持为空
        }
    }

















//
//    /**
//     * 根据组别抽签
//     * @param trackDrawDTO
//     * @return
//     */
//    @Override
//    public Result<List<TrackDrawDO>> trackDrawList(TrackDrawDO trackDrawDTO, Integer type) {
//        if (trackDrawDTO.getCbatchId() == null) {
//            return Result.fail("请先选择抽签批次！");
//        }
//
//        // 获取抽签列表
//        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
//        wrapper.eq("cbatch_id", trackDrawDTO.getCbatchId());
//        wrapper.orderBy(true, "sort");
//        List<TrackDrawDO> trackDrawDOS = this.selectList(wrapper);
//
//        // 为recordNumber随机分配具体的赛场编号
//        if (!trackDrawDOS.isEmpty()) {
//            assignVenueNumbers(trackDrawDOS);
//        }
//
//        if(null!=trackDrawDOS && !trackDrawDOS.isEmpty()){
//            this.updateBatchById(trackDrawDOS);
//        }
//
//        return Result.ok(trackDrawDOS);
//    }
//
//
//
//
//
//
//    /**
//     * 生成赛场编号列表
//     * @param venueRange 如"A01-A17"
//     * @return 该赛场的所有编号列表
//     */
//    private List<String> generateVenueNumbers(String venueRange) {
//        List<String> numbers = new ArrayList<>();
//        String[] parts = venueRange.split("-");
//
//        if (parts.length != 2) {
//            return numbers;
//        }
//
//        String prefix = parts[0].substring(0, 1); // 获取字母前缀
//        int start = Integer.parseInt(parts[0].substring(1));
//        int end = Integer.parseInt(parts[1].substring(1));
//
//        for (int i = start; i <= end; i++) {
//            numbers.add(prefix + String.format("%02d", i));
//        }
//
//        return numbers;
//    }
//
//
//
//
//
//
//
//
//
//
//
//    // 赛场定义
//    private static final String A_VENUE = "A01-A17";
//    private static final String B_VENUE = "B01-B16";
//    private static final String C_VENUE = "C01-C16";
//
//    /**
//     * 为每个参赛队伍分配具体的赛场编号
//     */
//    private void assignVenueNumbers(List<TrackDrawDO> trackDrawList) {
//        SecureRandom random = new SecureRandom();
//
//        // 准备各赛场的可用编号
//        List<String> aNumbers = generateVenueNumbers(A_VENUE);
//        List<String> bNumbers = generateVenueNumbers(B_VENUE);
//        List<String> cNumbers = generateVenueNumbers(C_VENUE);
//
//        // 打乱各赛场编号顺序以确保随机性
//        Collections.shuffle(aNumbers);
//        Collections.shuffle(bNumbers);
//        Collections.shuffle(cNumbers);
//
//        // 为每个参赛队伍分配编号
//        for (TrackDrawDO trackDraw : trackDrawList) {
//            // 随机选择赛场类型
//            int venueType = random.nextInt(3);
//
//            String venueNumber;
//            switch (venueType) {
//                case 0:
//                    if (!aNumbers.isEmpty()) {
//                        venueNumber = aNumbers.remove(0);
//                    } else if (!bNumbers.isEmpty()) {
//                        venueNumber = bNumbers.remove(0);
//                    } else {
//                        venueNumber = cNumbers.remove(0);
//                    }
//                    break;
//                case 1:
//                    if (!bNumbers.isEmpty()) {
//                        venueNumber = bNumbers.remove(0);
//                    } else if (!cNumbers.isEmpty()) {
//                        venueNumber = cNumbers.remove(0);
//                    } else {
//                        venueNumber = aNumbers.remove(0);
//                    }
//                    break;
//                case 2:
//                    if (!cNumbers.isEmpty()) {
//                        venueNumber = cNumbers.remove(0);
//                    } else if (!aNumbers.isEmpty()) {
//                        venueNumber = aNumbers.remove(0);
//                    } else {
//                        venueNumber = bNumbers.remove(0);
//                    }
//                    break;
//                default:
//                    venueNumber = "A01"; // 默认值
//            }
//
//            trackDraw.setRecordNumber(venueNumber);
//        }
//    }
//
//
//
//
//
//
//
//








    /**
     * 根据组别抽签
     * @param trackDrawDTO
     * @return
     */
    @Override
    public Result<List<TrackDrawDO>> trackDrawList(TrackDrawDO trackDrawDTO, Integer type) {
        if (trackDrawDTO.getCbatchId() == null) {
            return Result.fail("请先选择抽签批次！");
        }

        // 获取抽签列表
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.eq("cbatch_id", trackDrawDTO.getCbatchId());
        wrapper.orderBy(true, "sort");
        List<TrackDrawDO> trackDrawDOS = this.selectList(wrapper);

        // 为recordNumber随机分配具体的赛场编号
        if (!trackDrawDOS.isEmpty()) {
            assignVenueNumbers(trackDrawDOS);
        }

        if(null!=trackDrawDOS && !trackDrawDOS.isEmpty()){
            this.updateBatchById(trackDrawDOS);
        }

        return Result.ok(trackDrawDOS);
    }

    @Override
    public Result<List<XinJiangTrackVO>> trackDrawList2(TrackDrawDO trackDrawDTO, int i) {
        if (trackDrawDTO.getCbatchId() == null) {
            return Result.fail("请先选择抽签批次！");
        }

        // 获取抽签列表
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.eq("cbatch_id", trackDrawDTO.getCbatchId());
        wrapper.orderBy(true, "sort");
        List<TrackDrawDO> trackDrawDOS = this.selectList(wrapper);

        // 生成两个list 1-50号 51-100号
        List<Integer> siteA = generateShuffledList(1, trackDrawDOS.size());
        List<Integer> siteB = generateShuffledList(trackDrawDOS.size() + 1, trackDrawDOS.size() * 2);

        //格式VO
        AtomicInteger cursor = new AtomicInteger();
        List<XinJiangTrackVO> trackVOList = trackDrawDOS.stream().map(trackDrawDO -> {
            XinJiangTrackVO xinJiangTrackVO = new XinJiangTrackVO();
            xinJiangTrackVO.setUnitName(trackDrawDO.getUnitName());
            xinJiangTrackVO.setName1(trackDrawDO.getName1());
            xinJiangTrackVO.setSort1(siteA.get(cursor.get()));
            xinJiangTrackVO.setName2(trackDrawDO.getName2());
            xinJiangTrackVO.setSort2(siteB.get(cursor.get()));

            // 伪随机交换
            if (xinJiangTrackVO.getSort1() % 2 == 0 || xinJiangTrackVO.getSort2() % 3 == 0) {
                swap(xinJiangTrackVO);
            }
            trackDrawDO.setSort2(xinJiangTrackVO.getSort2());
            trackDrawDO.setSort1(xinJiangTrackVO.getSort1());

            // 固定选手 判断需要固定的选手是否在A赛道 固定林科大1选手为A赛道
            if (xinJiangTrackVO.getName1().equals("林科大1") && xinJiangTrackVO.getSort1() < siteA.size()) {
                // 交换A B选手顺序
                swap(xinJiangTrackVO);
            }
            // 保存抽签结果
            this.updateById(trackDrawDO);
            // 下标移动
            cursor.getAndIncrement();

            return xinJiangTrackVO;
        }).collect(Collectors.toList());

        return Result.ok(trackVOList);
    }

    @Override
    public Result<List<XinJiangTrackVO>> trackList2(TrackDrawDO trackDrawDTO) {
        if (trackDrawDTO.getCbatchId()==null){
            return Result.fail("请先选择抽签批次！");
        }
        //存储抽签你信息
        boolean hasDraw = true;//默认为true.不存在上次抽签结果时改为false

        //查询上一次的抽签结果
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.eq("cbatch_id",trackDrawDTO.getCbatchId());
        wrapper.orderBy(true,"sort");
        List<TrackDrawDO> trackDrawDOS = this.selectList(wrapper);

        // 未导入队伍
        if (trackDrawDOS.size() < 0) {
            return new Result<>(new ArrayList<XinJiangTrackVO>());
        }

        // XinJiangTrackVO格式
        List<XinJiangTrackVO> trackVOList = trackDrawDOS.stream().map(trackDrawDO -> {
            XinJiangTrackVO xinJiangTrackVO = new XinJiangTrackVO();
            xinJiangTrackVO.setUnitName(trackDrawDO.getUnitName());
            xinJiangTrackVO.setName1(trackDrawDO.getName1());
            xinJiangTrackVO.setSort1(trackDrawDO.getSort1());

            xinJiangTrackVO.setName2(trackDrawDO.getName2());
            xinJiangTrackVO.setSort2(trackDrawDO.getSort2());

            return xinJiangTrackVO;
        }).collect(Collectors.toList());

        return Result.ok(trackVOList);
    }

    /**
     * 生成赛场编号列表
     * @param venueRange 如"A01-A17"
     * @return 该赛场的所有编号列表
     */
    private List<String> generateVenueNumbers(String venueRange) {
        List<String> numbers = new ArrayList<>();
        String[] parts = venueRange.split("-");

        if (parts.length != 2) {
            return numbers;
        }

        String prefix = parts[0].substring(0, 1); // 获取字母前缀
        int start = Integer.parseInt(parts[0].substring(1));
        int end = Integer.parseInt(parts[1].substring(1));

        for (int i = start; i <= end; i++) {
            numbers.add(prefix + String.format("%02d", i));
        }

        return numbers;
    }

    /**
     * 生成指定范围 [start, end] 的整数列表，并随机打乱顺序
     * @param start 起始整数（包含）
     * @param end 结束整数（包含）
     * @return 打乱后的列表
     */
    private static List<Integer> generateShuffledList(int start, int end) {
        // 1. 创建有序列表，添加 [start, end] 范围内的整数
        List<Integer> list = new ArrayList<>();
        for (int i = start; i <= end; i++) {
            list.add(i);
        }

        // 2. 打乱列表顺序（使用 Collections.shuffle() 方法，随机置换元素）
        Collections.shuffle(list);

        return list;
    }

    /**
     * 交换sort1 sort2
     * @param xinJiangTrackVO
     */
    private static void swap(XinJiangTrackVO xinJiangTrackVO) {
        Integer tempSort = xinJiangTrackVO.getSort1();
        xinJiangTrackVO.setSort1(xinJiangTrackVO.getSort2());
        xinJiangTrackVO.setSort2(tempSort);
    }









    // 赛场定义
    private static final String A_VENUE = "A01-A17";
    private static final String B_VENUE = "B01-B16";
    private static final String C_VENUE = "C01-C16";

    /**
     * 为每个参赛队伍分配具体的赛场编号
     */
    private void assignVenueNumbers(List<TrackDrawDO> trackDrawList) {
        SecureRandom random = new SecureRandom();

        // 准备各赛场的可用编号
        List<String> aNumbers = generateVenueNumbers(A_VENUE);
        List<String> bNumbers = generateVenueNumbers(B_VENUE);
        List<String> cNumbers = generateVenueNumbers(C_VENUE);

        // 打乱各赛场编号顺序以确保随机性
        Collections.shuffle(aNumbers);
        Collections.shuffle(bNumbers);
        Collections.shuffle(cNumbers);

        // 先处理所有固定编号的分配
        for (TrackDrawDO trackDraw : trackDrawList) {
            String placeNum = trackDraw.getPlaceNum();
            if (placeNum != null && !placeNum.isEmpty() && placeNum.matches("^[A-C]\\d{2}$")) {
                // 从对应赛场的编号列表中移除这个固定编号，避免重复分配
                switch (placeNum.charAt(0)) {
                    case 'A':
                        aNumbers.remove(placeNum);
                        break;
                    case 'B':
                        bNumbers.remove(placeNum);
                        break;
                    case 'C':
                        cNumbers.remove(placeNum);
                        break;
                }
            }
        }

        // 为每个参赛队伍分配编号
        for (TrackDrawDO trackDraw : trackDrawList) {
            String placeNum = trackDraw.getPlaceNum();
            String venueNumber = null;

            // 如果placeNum有值，则根据值分配赛场
            if (placeNum != null && !placeNum.isEmpty()) {
                if (placeNum.matches("^[A-C]\\d{2}$")) {
                    // 如果是指定具体编号（如B10）
                    venueNumber = placeNum;
                } else if (placeNum.equalsIgnoreCase("A")) {
                    if (!aNumbers.isEmpty()) {
                        venueNumber = aNumbers.remove(0);
                    }
                } else if (placeNum.equalsIgnoreCase("B")) {
                    if (!bNumbers.isEmpty()) {
                        venueNumber = bNumbers.remove(0);
                    }
                } else if (placeNum.equalsIgnoreCase("C")) {
                    if (!cNumbers.isEmpty()) {
                        venueNumber = cNumbers.remove(0);
                    }
                }
            }

            // 如果没有通过placeNum分配到赛场，则随机分配
            if (venueNumber == null) {
                int venueType = random.nextInt(3);
                switch (venueType) {
                    case 0:
                        if (!aNumbers.isEmpty()) {
                            venueNumber = aNumbers.remove(0);
                        } else if (!bNumbers.isEmpty()) {
                            venueNumber = bNumbers.remove(0);
                        } else {
                            venueNumber = cNumbers.remove(0);
                        }
                        break;
                    case 1:
                        if (!bNumbers.isEmpty()) {
                            venueNumber = bNumbers.remove(0);
                        } else if (!cNumbers.isEmpty()) {
                            venueNumber = cNumbers.remove(0);
                        } else {
                            venueNumber = aNumbers.remove(0);
                        }
                        break;
                    case 2:
                        if (!cNumbers.isEmpty()) {
                            venueNumber = cNumbers.remove(0);
                        } else if (!aNumbers.isEmpty()) {
                            venueNumber = aNumbers.remove(0);
                        } else {
                            venueNumber = bNumbers.remove(0);
                        }
                        break;
                    default:
                        venueNumber = "A01"; // 默认值
                }
            }

            trackDraw.setRecordNumber(venueNumber);
        }
    }




    /**
     * 查询上一次的抽签结果
     * @param trackDrawDTO
     * @return
     */
    @Override
    @Transactional
    public Result<List<TrackDrawDO>> trackList(TrackDrawDO trackDrawDTO) {
        if (trackDrawDTO.getCbatchId()==null){
            return Result.fail("请先选择抽签批次！");
        }
        //存储抽签你信息
        boolean hasDraw = true;//默认为true.不存在上次抽签结果时改为false

        //查询上一次的抽签结果
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.eq("cbatch_id",trackDrawDTO.getCbatchId());
        wrapper.orderBy(true,"sort");
        List<TrackDrawDO> trackDrawDOS = this.selectList(wrapper);

        //如果没有抽签上一次抽签结果那就默认初始化
        if(trackDrawDOS==null || trackDrawDOS.size()==0){
            trackDrawDOS = new ArrayList<>();
            hasDraw = false;
            return Result.ok(trackDrawDOS);
        }else {
            if (trackDrawDOS.get(0).getRecordNumber()==null) {
                hasDraw = false;
            }
        }
        int size = trackDrawDOS.size();
        List<TrackDrawDO> trackDrawDOS1 = setTemplate(trackDrawDOS);
        trackDrawDOS1.get(0).setHasDraw(hasDraw);
        trackDrawDOS1.get(0).setTotal(size);
        return Result.ok(trackDrawDOS1);
    }




    /**
     * 查询上一次的抽签结果
     * @param trackDrawDTO
     * @return
     */
    @Override
    @Transactional
    public Result<List<TrackDrawDO>> trackList1(TrackDrawDO trackDrawDTO) {
        if (trackDrawDTO.getCbatchId()==null){
            return Result.fail("请先选择抽签批次！");
        }
        //存储抽签你信息
        boolean hasDraw = true;//默认为true.不存在上次抽签结果时改为false

        //查询上一次的抽签结果
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.eq("cbatch_id",trackDrawDTO.getCbatchId());
        wrapper.orderBy(true,"check_name1");
        wrapper.orderBy(true,"check_name2");
        List<TrackDrawDO> trackDrawDOS = this.selectList(wrapper);

        //如果没有抽签上一次抽签结果那就默认初始化
        if(trackDrawDOS==null || trackDrawDOS.size()==0){
            trackDrawDOS = new ArrayList<>();
            hasDraw = false;
            return Result.ok(trackDrawDOS);
        }else {
            if (trackDrawDOS.get(0).getRecordNumber()==null) {
                hasDraw = false;
            }
        }
        int size = trackDrawDOS.size();
        List<TrackDrawDO> trackDrawDOS1 = setTemplate(trackDrawDOS);
        trackDrawDOS1.get(0).setHasDraw(hasDraw);
        trackDrawDOS1.get(0).setTotal(size);
        return Result.ok(trackDrawDOS1);
    }



    /**
     * 导入抽签参赛院校
     *
     * @param file
     * @return
     */
    @Override
    public Result<Object> importExcelTrackDraw(MultipartFile file,Long cbatchId) {
        if (cbatchId==null){
            return Result.fail("请先选择导入抽签批次！");
        }
        List<TrackDrawDownLoadDO> lottery = new ArrayList<>();
        if (!"application/vnd.ms-excel".equals(file.getContentType())) {
            return Result.fail("文件格式错误，请选择.xls文件");
        }
        try {
            InputStream inputStream = file.getInputStream();
            lottery = EasyExcel.read(inputStream)
                    // 这个转换是成全局的， 所有java为string,excel为string的都会用这个转换器。
                    // 如果就想单个字段使用请使用@ExcelProperty 指定converter
                    .registerConverter(new StringConverter())
                    // 注册监听器，可以在这里校验字段
                    .registerReadListener(new CustomerDailyImportListener2())
                    .head(TrackDrawDownLoadDO.class)
                    .sheet()
                    .headRowNumber(2)
                    .doReadSync();
        } catch (Exception e) {
            e.getMessage();
            e.printStackTrace();
            return Result.fail(e.getMessage());
        }
        if (lottery.isEmpty()) {
            return Result.fail("Excel数据为空，请检查");
        }
        boolean b = true;
        // 查询是否进行过导入
        List<TrackDrawDO> trackDrawDOS = this.selectList(new EntityWrapper<TrackDrawDO>()
                .eq("cbatch_id",cbatchId)
                .orderBy("sort", true));
        // 为空没进行导入，将数据插入到数据库
        if (trackDrawDOS.isEmpty()) {
            for (int i = 0; i < lottery.size(); i++) {
                TrackDrawDO trackDrawDO = new TrackDrawDO();
                trackDrawDO.setSort(i+1);
                trackDrawDO.setCbatchId(cbatchId);
                trackDrawDO.setUnitName(lottery.get(i).getUnitName());
                trackDrawDOS.add(trackDrawDO);
            }
            b = this.insertBatch(trackDrawDOS);
        }else{
            // 导入后新增的学校
            List<TrackDrawDO> trackDrawDOS1=new ArrayList<>();
            // 获取导入后的最大排序数
            Integer sort = trackDrawDOS.get(trackDrawDOS.size() - 1).getSort();
            // 进行过导入，校验是否重复
            for (int i = 0; i < lottery.size(); i++) {
                TrackDrawDO trackDrawDO = new TrackDrawDO();
                for (int j = 0; j < trackDrawDOS.size(); j++) {
                    if (lottery.get(i).getUnitName().equals(trackDrawDOS.get(j).getUnitName())) {
                        return Result.fail("第" + (i+1) + "行参赛学校已存在，请检查");
                    }
                }
                // 设置排序数量
                trackDrawDO.setSort(sort+1);
                sort++;
                // 设置学校名称
                trackDrawDO.setUnitName(lottery.get(i).getUnitName());
                trackDrawDO.setCbatchId(cbatchId);
                trackDrawDOS1.add(trackDrawDO);
            }
            b=this.insertBatch(trackDrawDOS1);
        }

        return b?Result.ok():Result.fail();
    }



    /**
     * 导入抽签参赛院校
     *
     * @param file
     * @return
     */
    @Override
    public Result<TrackDrawName4> importExcelTrackDraw1(MultipartFile file, Long cbatchId) {
        if (cbatchId==null){
            return Result.fail("请先选择导入抽签批次！");
        }
        //清空原始信息
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.eq("cbatch_id",cbatchId);
        this.delete(wrapper);
        List<TrackDrawName4> lottery = new ArrayList<>();
        if (!"application/vnd.ms-excel".equals(file.getContentType())) {
            return Result.fail("文件格式错误，请选择.xls文件");
        }
        try {
            InputStream inputStream = file.getInputStream();
            lottery = EasyExcel.read(inputStream)
                    // 这个转换是成全局的， 所有java为string,excel为string的都会用这个转换器。
                    // 如果就想单个字段使用请使用@ExcelProperty 指定converter
                    .registerConverter(new StringConverter())
                    // 注册监听器，可以在这里校验字段
                    .registerReadListener(new CustomerDailyImportListener4())
                    .head(TrackDrawName4.class)
                    .sheet()
                    .headRowNumber(2)
                    .doReadSync();
        } catch (Exception e) {
            e.getMessage();
            e.printStackTrace();
            return Result.fail(e.getMessage());
        }
        if (lottery.isEmpty()) {
            return Result.fail("Excel数据为空，请检查");
        }
        boolean b = true;
        // 查询是否进行过导入
        List<TrackDrawDO> trackDrawDOS = this.selectList(new EntityWrapper<TrackDrawDO>()
                .eq("cbatch_id",cbatchId)
                .orderBy("sort", true));
        // 为空没进行导入，将数据插入到数据库
        if (trackDrawDOS.isEmpty()) {
            for (int i = 0; i < lottery.size(); i++) {
                TrackDrawDO trackDrawDO = new TrackDrawDO();
                trackDrawDO.setSort(i+1);
                trackDrawDO.setCbatchId(cbatchId);
                trackDrawDO.setUnitName(lottery.get(i).getUnitName());
                trackDrawDO.setName1(lottery.get(i).getName1());
                trackDrawDO.setName2(lottery.get(i).getName2());
                if (StringUtils.isNotEmpty(lottery.get(i).getName3())){
                    trackDrawDO.setName3(lottery.get(i).getName3());
                }
                if (StringUtils.isNotEmpty(lottery.get(i).getName4())){
                    trackDrawDO.setName4(lottery.get(i).getName4());
                }
                if (StringUtils.isNotEmpty(lottery.get(i).getName3())){
                    trackDrawDO.setFixedName1(lottery.get(i).getFixedName1());
                }
                if (StringUtils.isNotEmpty(lottery.get(i).getName4())){
                    trackDrawDO.setFixedName2(lottery.get(i).getFixedName2());
                }
                if (StringUtils.isNotEmpty(lottery.get(i).getPlaceNum())){
                    trackDrawDO.setPlaceNum(lottery.get(i).getPlaceNum());
                }
                trackDrawDOS.add(trackDrawDO);
            }
            b = this.insertBatch(trackDrawDOS);
        }else{
            // 导入后新增的学校
            List<TrackDrawDO> trackDrawDOS1=new ArrayList<>();
            // 获取导入后的最大排序数
            Integer sort = trackDrawDOS.get(trackDrawDOS.size() - 1).getSort();
            // 进行过导入，校验是否重复
            for (int i = 0; i < lottery.size(); i++) {
                TrackDrawDO trackDrawDO = new TrackDrawDO();
                /*for (int j = 0; j < trackDrawDOS.size(); j++) {
                    if (lottery.get(i).getUnitName().equals(trackDrawDOS.get(j).getUnitName())) {
                        return Result.fail("第" + (i+1) + "行参赛学校已存在，请检查");
                    }
                }*/
                // 设置排序数量
                trackDrawDO.setSort(sort+1);
                sort++;
                // 设置学校名称
                trackDrawDO.setUnitName(lottery.get(i).getUnitName());
                trackDrawDO.setCbatchId(cbatchId);
                trackDrawDO.setName1(lottery.get(i).getName1());
                trackDrawDO.setName2(lottery.get(i).getName2());
                if (StringUtils.isNotEmpty(lottery.get(i).getName3())){
                    trackDrawDO.setName3(lottery.get(i).getName3());
                }
                if (StringUtils.isNotEmpty(lottery.get(i).getName4())){
                    trackDrawDO.setName4(lottery.get(i).getName4());
                }
                if (StringUtils.isNotEmpty(lottery.get(i).getPlaceNum())){
                    trackDrawDO.setPlaceNum(lottery.get(i).getPlaceNum());
                }
                trackDrawDOS1.add(trackDrawDO);
            }
            b=this.insertBatch(trackDrawDOS1);
        }

        return b?Result.ok():Result.fail();
    }


    @Override
    public Result<List<TrackDrawDO>> startDraw(TrackDrawDO trackDrawDTO){
        if (trackDrawDTO.getCbatchId() == null) {
            return Result.fail("请先选择抽签批次！");
        }
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.eq("cbatch_id", trackDrawDTO.getCbatchId());
        wrapper.orderBy(true, "sort");
        List<TrackDrawDO> trackDrawDOS = this.selectList(wrapper);

        // 判断是否进行导入学校
        if (trackDrawDOS.size() <= 0) {
            return Result.fail("请先导入学校！");
        }
        LinkedList<String> numList = new LinkedList<>();
        Random random = new Random();
        // 将查询到的学校放入抽签列表中
        for (int i = 1; i <= trackDrawDOS.size(); i++) {
            numList.add(String.valueOf(i));
        }
        List<TrackDrawDO> filteredList = trackDrawDOS.stream()
                .filter(trackDrawDO -> trackDrawDO.getPlaceNum() != null && !trackDrawDO.getPlaceNum().isEmpty())
                .collect(Collectors.toList());
        // 将指定的检录号从数组中移除
        filteredList.forEach(trackDrawDO ->{
            if(StringUtil.notEmpty(trackDrawDO.getPlaceNum())){
                numList.remove(trackDrawDO.getPlaceNum());
            }
        });

        //打乱一下存放检录号的列表
        Collections.shuffle(numList,random);
        // 遍历设置检录号
        for (TrackDrawDO record : trackDrawDOS) {
            String recordNumber = "";
            Integer recordNumberSort=null;
            //判断检录序号是否需要固定
            if(StringUtil.notEmpty(record.getPlaceNum())){
                recordNumberSort= Integer.valueOf(record.getPlaceNum());
                //recordNumber=rule+record.getPlaceNum();
                recordNumber=record.getPlaceNum();
                record.setRecordNumberSort(Integer.parseInt(record.getPlaceNum()));
                numList.remove(record.getPlaceNum());
            }else{
                recordNumberSort= Integer.valueOf(numList.getFirst());
                //recordNumber=rule+numList.getFirst();
                recordNumber=numList.getFirst();
                record.setRecordNumberSort(Integer.parseInt(numList.getFirst()));
                numList.removeFirst();
            }
            //设置检录号
            record.setRecordNumber(recordNumber);
            record.setRecordNumberSort(recordNumberSort);
            //抽取选手
            handlePlayerSelection(record,random);
        }


        this.updateBatchById(trackDrawDOS);
        return Result.ok(trackDrawDOS);
    }

    /**
     * 执行抽签逻辑（从4个选手中抽取2个）
     */
    private TrackDrawDO executeDraw(TrackDrawDO trackDraw) {
        // 获取所有选手
        List<String> allPlayers = Arrays.asList(
                trackDraw.getName1(), trackDraw.getName2(),
                trackDraw.getName3(), trackDraw.getName4()
        ).stream().filter(Objects::nonNull).collect(Collectors.toList());

        // 获取固定选手
        List<String> fixedPlayers = Arrays.asList(
                trackDraw.getFixedName1(), trackDraw.getFixedName2()
        ).stream().filter(Objects::nonNull).collect(Collectors.toList());

        // 计算需要抽取的数量
        int drawCount = 2 - fixedPlayers.size();

        // 获取剩余选手
        List<String> remainingPlayers = allPlayers.stream()
                .filter(player -> !fixedPlayers.contains(player))
                .collect(Collectors.toList());

        // 随机抽取
        List<String> selectedPlayers = new ArrayList<>(fixedPlayers);
        if (drawCount > 0) {
            // 使用recordNumberSort作为随机种子，确保结果可重现
            Random random = new Random(System.currentTimeMillis());
            Collections.shuffle(remainingPlayers, random);

            // 抽取所需数量的选手
            selectedPlayers.addAll(remainingPlayers.subList(0, Math.min(drawCount, remainingPlayers.size())));
        }

        // 设置抽中选手
        if (selectedPlayers.size() > 0) trackDraw.setCheckName1(selectedPlayers.get(0));
        if (selectedPlayers.size() > 1) trackDraw.setCheckName2(selectedPlayers.get(1));

        trackDraw.setHasDraw(true);
        return trackDraw;
    }

    /**
     * 导出抽签结果
     * @param trackDrawDTO
     * @return
     */
    @Override
    public void exportDraw(HttpServletResponse response, TrackDrawDO trackDrawDTO){
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.eq("cbatch_id", trackDrawDTO.getCbatchId());
        wrapper.orderBy(true, "sort");
        List<TrackDrawDO> trackDrawDOS = this.selectList(wrapper);
        List<TrackDrawName4Export> trackDrawDownLoadDOS = new ArrayList<>();
        trackDrawDOS.forEach(a->{
            TrackDrawName4Export export = new TrackDrawName4Export();
            export.setNames(a.getName1()+"、"+a.getName2()+"、"+a.getName3()+"、"+a.getName4());
            export.setCheckNames(a.getCheckName1()+"、"+a.getCheckName2());
            export.setRecordNumber(a.getRecordNumber());
            export.setUnitName(a.getUnitName());
            trackDrawDownLoadDOS.add(export);
        });
        //导出操作
        EasyPoiUtil.exportExcel(trackDrawDownLoadDOS, "大赛抽签", "大赛抽签", TrackDrawName4Export.class,  "大赛抽签", response);
    }



    /**
     * 查询列表
     * @param trackDrawDTO
     * @return
     */
    @Override
    public List<TrackDrawDO> exportDrawList(TrackDrawDO trackDrawDTO){
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.eq("cbatch_id", trackDrawDTO.getCbatchId());
        wrapper.orderBy(true, "sort");
        List<TrackDrawDO> trackDrawDOS = this.selectList(wrapper);
        return trackDrawDOS;
    }

    @Override
    public Result<Object> importExcelTrackDrawXinJiang(MultipartFile file, Long cbatchId) {

        return null;
    }

    /**
     * 处理抽签结果数据，改成4*18格式
     */
    public List<TrackDrawDO> setTemplate(List<TrackDrawDO> trackDrawDOS){
        List<TrackDrawDO> trackDrawDOSCopy = new ArrayList<>();//存储最终的抽签结果

        //存储每一行的抽签结果
        TrackDrawDO trackDrawDO1 = new TrackDrawDO();
        List<TrackDrawDO> trackDrawDOSO1 = new ArrayList<>();
        for (int i = 0; i < trackDrawDOS.size(); i++) {
            trackDrawDOSO1.add(trackDrawDOS.get(i));
            if((i+1) % 3 == 0){
                trackDrawDO1.setTrackDrawDOList(trackDrawDOSO1);
                trackDrawDOSCopy.add(trackDrawDO1);
                //清空
                trackDrawDO1 = new TrackDrawDO();
                trackDrawDOSO1 = new ArrayList<>();
            } else if (trackDrawDOS.size()-(i+1)==0) {
                trackDrawDO1.setTrackDrawDOList(trackDrawDOSO1);
                trackDrawDOSCopy.add(trackDrawDO1);
            }
        }
        return trackDrawDOSCopy;
    }

}


